"""
几何图形计算器 - 完整版
开发者：谢林杞、鄢圣峰
班级：23040101
学号：20232807、20232810
"""

import math


class GeometryCalculator:
    """几何图形计算器主类"""

    def __init__(self):
        self.shapes = {
            '1': '圆形',
            '2': '三角形',
            '3': '正方形',
            '4': '长方形',
            '5': '平行四边形'
        }

    def display_menu(self):
        """显示主菜单"""
        print("\n" + "=" * 50)
        print("           几何图形计算器")
        print("=" * 50)
        for key, value in self.shapes.items():
            print(f"  {key}. {value}")
        print("  6. 运行所有测试")
        print("  0. 退出程序")
        print("=" * 50)

    def get_positive_number(self, prompt):
        """获取正数输入"""
        while True:
            try:
                value = float(input(prompt))
                if value <= 0:
                    print("错误：请输入一个正数！")
                    continue
                return value
            except ValueError:
                print("错误：请输入有效的数字！")

    def calculate_circle(self):
        """计算圆形的面积和周长 - 谢林杞负责"""
        print("\n--- 圆形计算 ---")
        radius = self.get_positive_number("请输入圆的半径: ")

        area = math.pi * radius ** 2
        perimeter = 2 * math.pi * radius

        print(f"\n圆形计算结果:")
        print(f"半径: {radius}")
        print(f"面积: {area:.2f}")
        print(f"周长: {perimeter:.2f}")
        return area, perimeter

    def calculate_triangle(self):
        """计算三角形的面积和周长 - 鄢圣峰负责"""
        print("\n--- 三角形计算 ---")
        a = self.get_positive_number("请输入第一条边长: ")
        b = self.get_positive_number("请输入第二条边长: ")
        c = self.get_positive_number("请输入第三条边长: ")

        # 验证三角形是否有效
        if a + b <= c or a + c <= b or b + c <= a:
            print("错误：输入的边长无法构成有效的三角形！")
            return None, None

        # 计算周长
        perimeter = a + b + c

        # 使用海伦公式计算面积
        s = perimeter / 2
        area = math.sqrt(s * (s - a) * (s - b) * (s - c))

        print(f"\n三角形计算结果:")
        print(f"边长: {a}, {b}, {c}")
        print(f"面积: {area:.2f}")
        print(f"周长: {perimeter:.2f}")
        return area, perimeter

    def calculate_square(self):
        """计算正方形的面积和周长 - 谢林杞负责"""
        print("\n--- 正方形计算 ---")
        side = self.get_positive_number("请输入正方形的边长: ")

        area = side ** 2
        perimeter = 4 * side

        print(f"\n正方形计算结果:")
        print(f"边长: {side}")
        print(f"面积: {area:.2f}")
        print(f"周长: {perimeter:.2f}")
        return area, perimeter

    def calculate_rectangle(self):
        """计算长方形的面积和周长 - 鄢圣峰负责"""
        print("\n--- 长方形计算 ---")
        length = self.get_positive_number("请输入长方形的长: ")
        width = self.get_positive_number("请输入长方形的宽: ")

        area = length * width
        perimeter = 2 * (length + width)

        print(f"\n长方形计算结果:")
        print(f"长: {length}, 宽: {width}")
        print(f"面积: {area:.2f}")
        print(f"周长: {perimeter:.2f}")
        return area, perimeter

    def calculate_parallelogram(self):
        """计算平行四边形的面积和周长 - 谢林杞负责"""
        print("\n--- 平行四边形计算 ---")
        base = self.get_positive_number("请输入平行四边形的底: ")
        side = self.get_positive_number("请输入平行四边形的斜边: ")
        height = self.get_positive_number("请输入平行四边形的高: ")

        area = base * height
        perimeter = 2 * (base + side)

        print(f"\n平行四边形计算结果:")
        print(f"底: {base}, 斜边: {side}, 高: {height}")
        print(f"面积: {area:.2f}")
        print(f"周长: {perimeter:.2f}")
        return area, perimeter

    def run_all_tests(self):
        """运行所有测试用例"""
        print("\n" + "=" * 60)
        print("                   测试结果")
        print("=" * 60)

        test_results = []

        # 测试圆形
        print("\n1. 测试圆形计算:")
        radius = 5
        expected_area = math.pi * 25
        expected_perimeter = 2 * math.pi * 5
        actual_area = math.pi * radius ** 2
        actual_perimeter = 2 * math.pi * radius

        area_ok = abs(actual_area - expected_area) < 0.01
        perimeter_ok = abs(actual_perimeter - expected_perimeter) < 0.01

        status = "✅ 通过" if area_ok and perimeter_ok else "❌ 失败"
        test_results.append(("圆形", status))
        print(f"   半径={radius}, 面积={actual_area:.2f}, 周长={actual_perimeter:.2f} - {status}")

        # 测试正方形
        print("\n2. 测试正方形计算:")
        side = 4
        expected_area = 16
        expected_perimeter = 16
        actual_area = side ** 2
        actual_perimeter = 4 * side

        area_ok = actual_area == expected_area
        perimeter_ok = actual_perimeter == expected_perimeter

        status = "✅ 通过" if area_ok and perimeter_ok else "❌ 失败"
        test_results.append(("正方形", status))
        print(f"   边长={side}, 面积={actual_area}, 周长={actual_perimeter} - {status}")

        # 测试长方形
        print("\n3. 测试长方形计算:")
        length, width = 5, 3
        expected_area = 15
        expected_perimeter = 16
        actual_area = length * width
        actual_perimeter = 2 * (length + width)

        area_ok = actual_area == expected_area
        perimeter_ok = actual_perimeter == expected_perimeter

        status = "✅ 通过" if area_ok and perimeter_ok else "❌ 失败"
        test_results.append(("长方形", status))
        print(f"   长={length}, 宽={width}, 面积={actual_area}, 周长={actual_perimeter} - {status}")

        # 测试三角形
        print("\n4. 测试三角形计算:")
        a, b, c = 3, 4, 5
        s = (a + b + c) / 2
        expected_area = 6.0  # 3-4-5直角三角形的面积
        expected_perimeter = 12
        actual_area = math.sqrt(s * (s - a) * (s - b) * (s - c))
        actual_perimeter = a + b + c

        area_ok = abs(actual_area - expected_area) < 0.01
        perimeter_ok = actual_perimeter == expected_perimeter

        status = "✅ 通过" if area_ok and perimeter_ok else "❌ 失败"
        test_results.append(("三角形", status))
        print(f"   边长={a},{b},{c}, 面积={actual_area:.2f}, 周长={actual_perimeter} - {status}")

        # 测试平行四边形
        print("\n5. 测试平行四边形计算:")
        base, side_len, height = 6, 4, 3
        expected_area = 18
        expected_perimeter = 20
        actual_area = base * height
        actual_perimeter = 2 * (base + side_len)

        area_ok = actual_area == expected_area
        perimeter_ok = actual_perimeter == expected_perimeter

        status = "✅ 通过" if area_ok and perimeter_ok else "❌ 失败"
        test_results.append(("平行四边形", status))
        print(f"   底={base}, 斜边={side_len}, 高={height}, 面积={actual_area}, 周长={actual_perimeter} - {status}")

        # 显示测试总结
        print("\n" + "=" * 60)
        print("测试总结:")
        passed = sum(1 for _, status in test_results if "✅" in status)
        total = len(test_results)
        print(f"通过: {passed}/{total}")

        for shape, status in test_results:
            print(f"  {shape}: {status}")

        if passed == total:
            print("🎉 所有测试通过！程序运行正常。")
        else:
            print("⚠️  部分测试失败，请检查代码。")
        print("=" * 60)

    def run(self):
        """运行计算器主程序 - 鄢圣峰负责整合"""
        print("欢迎使用几何图形计算器！")

        while True:
            self.display_menu()
            choice = input("请选择操作 (0-6): ").strip()

            if choice == '0':
                print("感谢使用几何图形计算器，再见！")
                break
            elif choice == '1':
                self.calculate_circle()
            elif choice == '2':
                self.calculate_triangle()
            elif choice == '3':
                self.calculate_square()
            elif choice == '4':
                self.calculate_rectangle()
            elif choice == '5':
                self.calculate_parallelogram()
            elif choice == '6':
                self.run_all_tests()
            else:
                print("错误：请输入0-6之间的有效选项！")

            # 询问是否继续
            if choice != '0':
                continue_choice = input("\n是否继续计算？(y/n): ").strip().lower()
                if continue_choice != 'y':
                    print("感谢使用几何图形计算器，再见！")
                    break


def main():
    """主函数"""
    calculator = GeometryCalculator()

    # 显示欢迎信息
    print("=" * 60)
    print("          几何图形计算器 - 完整版")
    print("          开发者: 谢林杞、鄢圣峰")
    print("          班级: 23040101")
    print("=" * 60)

    calculator.run()


if __name__ == "__main__":
    main()